package ru.amse.tsyganov.jumleditor.view.repr;

import java.util.Collections;
import java.util.List;

import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;

import ru.amse.tsyganov.jumleditor.graphicaleditor.Coordinates;
import ru.amse.tsyganov.jumleditor.model.ActivityGraph;
import ru.amse.tsyganov.jumleditor.model.ForkJoinState;
import ru.amse.tsyganov.jumleditor.model.Transition;
import ru.amse.tsyganov.jumleditor.properties.EnumProperty;
import ru.amse.tsyganov.jumleditor.properties.StringProperty;
import ru.amse.tsyganov.jumleditor.validator.Problem;
import ru.amse.tsyganov.jumleditor.view.ConnectionPoint;
import ru.amse.tsyganov.jumleditor.view.PositionKeeper;
import ru.amse.tsyganov.jumleditor.view.ViewVisitor;
import ru.amse.tsyganov.jumleditor.view.ConnectionPoint.ConnectionPointType;
import ru.amse.tsyganov.jumleditor.view.activepoints.ActivePoint;

public class ForkJoinStateView<T extends ForkJoinState> extends StateView<T> {
	
	private static final int FORK_JOIN_WIDTH = 40;
	private static final int FORK_JOIN_HEIGHT = 10;
	
	private final List<ActivePoint> points;
	
	private final PositionKeeper[] horizontalPos = new PositionKeeper[6];
	
	private final PositionKeeper[] verticalPos = new PositionKeeper[6];

	public ForkJoinStateView(T model, 
			ActivityGraphView<? extends ActivityGraph> activityGraphView) {
		
		super(model, activityGraphView);
		points = createNominalActivePoints();
		initProperties();
		setWidth(FORK_JOIN_WIDTH);
		setHeight(FORK_JOIN_HEIGHT);
		
		horizontalPos[0] = new PositionKeeper() {
			public int getPosX() {
				return getX() + getWidth() / 4;
			}

			public int getPosY() {
				return getY();
			}
		};
		
		horizontalPos[1] = new PositionKeeper() {
			public int getPosX() {
				return getX() + getWidth() / 2;
			}

			public int getPosY() {
				return getY();
			}
		};
		
		horizontalPos[2] = new PositionKeeper() {
			public int getPosX() {
				return getX() + 3 * getWidth() / 4;
			}

			public int getPosY() {
				return getY();
			}
		};
		
		horizontalPos[3] = new PositionKeeper() {
			public int getPosX() {
				return getX() + getWidth() / 4;
			}

			public int getPosY() {
				return getY() + getHeight();
			}
		};
		
		horizontalPos[4] = new PositionKeeper() {
			public int getPosX() {
				return getX() + getWidth() / 2;
			}

			public int getPosY() {
				return getY() + getHeight();
			}
		};
		
		horizontalPos[5] = new PositionKeeper() {
			public int getPosX() {
				return getX() + 3 * getWidth() / 4;
			}

			public int getPosY() {
				return getY() + getHeight();
			}
		};
		
		horizontalPos[0] = new PositionKeeper() {
			public int getPosX() {
				return getX() + getWidth() / 4;
			}

			public int getPosY() {
				return getY();
			}
		};
		
		verticalPos[0] = new PositionKeeper() {
			public int getPosX() {
				return getX();
			}

			public int getPosY() {
				return getY() + 3 * getHeight() / 4;
			}
		};
		
		verticalPos[1] = new PositionKeeper() {
			public int getPosX() {
				return getX();
			}

			public int getPosY() {
				return getY() + getHeight() / 2;
			}
		};
		
		verticalPos[2] = new PositionKeeper() {
			public int getPosX() {
				return getX();
			}

			public int getPosY() {
				return getY() + getHeight() / 4;
			}
		};
		
		verticalPos[3] = new PositionKeeper() {
			public int getPosX() {
				return getX() + getWidth();
			}

			public int getPosY() {
				return getY() + 3 * getHeight() / 4;
			}
		};
		
		verticalPos[4] = new PositionKeeper() {
			public int getPosX() {
				return getX() + getWidth();
			}

			public int getPosY() {
				return getY() + getHeight() / 2;
			}
		};
		
		verticalPos[5] = new PositionKeeper() {
			public int getPosX() {
				return getX() + getWidth();
			}

			public int getPosY() {
				return getY() + getHeight() / 4;
			}
		};
		
		getConnectionPoints().clear();
		
		getConnectionPoints().add(new ConnectionPoint(
				ConnectionPointType.TOP, ForkJoinStateView.this, horizontalPos[0], 0));
		
		getConnectionPoints().add(new ConnectionPoint(
				ConnectionPointType.TOP, ForkJoinStateView.this, horizontalPos[1], 1));
		
		getConnectionPoints().add(new ConnectionPoint(
				ConnectionPointType.TOP, ForkJoinStateView.this, horizontalPos[2], 2));
		
		getConnectionPoints().add(new ConnectionPoint(
				ConnectionPointType.BOTTOM, ForkJoinStateView.this, horizontalPos[3], 3));
		
		getConnectionPoints().add(new ConnectionPoint(
				ConnectionPointType.BOTTOM, ForkJoinStateView.this, horizontalPos[4], 4));
		
		getConnectionPoints().add(new ConnectionPoint(
				ConnectionPointType.BOTTOM, ForkJoinStateView.this, horizontalPos[5], 5));
	}
	
	@Override
	public void accept(ViewVisitor v) {
		v.visitForkJoinStateView(this);
		visitTransitions(v);
	}

	@Override
	public void paintFigure(GC gc, Coordinates coordinates) {
		assert gc != null;
		
		gc.setBackground(getValidity().getColor());
		
		Rectangle r = getRectangle();
		gc.fillRectangle(
				coordinates.fromModelXToScreenX(r.x),
				coordinates.fromModelYToScreenY(r.y),
				r.width, r.height);
	}
	
	@Override
	public List<ActivePoint> getActivePoints() {
		if (getSelectedItems().selectedStatesContains(this)) {
			return points;
		} else {
			return Collections.emptyList();
		}
	}
	
	private void initProperties() {
		String[] elements = {"Vertical", "Horizontal"};
		
		super.getProperties().addProperty(
				new EnumProperty("Orientation", elements) {

			@Override
			public Integer getPropertyValue() {
				return (getWidth() > getHeight()) ? 1 : 0;
			}

			@Override
			public void setPropertyValue(Integer newValue) {
				int maxDim = Math.max(getWidth(), getHeight());
				int minDim = Math.min(getWidth(), getHeight());
				
				if (newValue == 0) {
					setWidth(minDim);
					setHeight(maxDim);
					int i = 0;
					for (ConnectionPoint p : getConnectionPoints()) {
						p.setPositionKeeper(verticalPos[i++]);
						p.setType(i < 3 ? ConnectionPointType.LEFT :
							ConnectionPointType.RIGHT);
					}
				} else {
					setWidth(maxDim);
					setHeight(minDim);
					int i = 0;
					for (ConnectionPoint p : getConnectionPoints()) {
						p.setPositionKeeper(horizontalPos[i++]);
						p.setType(i < 3 ? ConnectionPointType.TOP :
							ConnectionPointType.BOTTOM);
					}
				}
				for (Transition t : getModel().getStateVertex().getOutgoing()) {
					getActivityGraphView().getModelViewMap().
						getTransitionsMap().get(t).initBrokenLine();
				}
				for (Transition t : getModel().getStateVertex().getIncoming()) {
					getActivityGraphView().getModelViewMap().
						getTransitionsMap().get(t).initBrokenLine();
				}
			}

		});
	}
	
	@Override
	public StringProperty getMainProperty() {
		return null;
	}

	public String getClassName() {
		return "ForkJoinStateView";
	}

	@Override
	public List<Problem> getInnerProblems() {
		return Collections.emptyList();
	}
	
}
